#include "cpu/exec.h"
#include "memory/mmu.h"

void raise_intr(uint8_t NO, vaddr_t ret_addr) {
  /* TODO: Trigger an interrupt/exception with ``NO''.
   * That is, use ``NO'' to index the IDT.
   */
   // 1. 依次将 EFLAGS、CS、EIP 压入堆栈
  rtl_push(&cpu.eflags.val);
  cpu.eflags.IF = 0;
  rtl_push((const rtlreg_t*)&cpu.CS);
  rtl_push(&ret_addr);
  // 2. 从 IDTR 中读取 IDT 基地址
  uint32_t idt_base = cpu.idtr.base;
  uint16_t idt_limit = cpu.idtr.limit;
  // 3. 根据异常(中断)号在IDT中进行索引,找到一个门描述符
  assert(NO * 8 + 7 <= idt_limit);
  uint32_t idt_entry_addr = idt_base + NO * 8;
  uint32_t gate_low = vaddr_read(idt_entry_addr, 4);      // 读取低4字节
  uint32_t gate_high = vaddr_read(idt_entry_addr + 4, 4); // 读取高4字节
  // 4. 将门描述符中的offset域组合成目标地址
  uint32_t offset_low = gate_low & 0xffff;
  uint32_t offset_high = (gate_high >> 16) & 0xffff;
  uint32_t target_eip = (offset_high << 16) | offset_low;
  // 5. 跳转到目标地址
  decoding.jmp_eip = target_eip; 
  decoding.is_jmp = 1;
}

void dev_raise_intr() {
  cpu.INTR = true;
}
